home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / The World of Computer Software.iso / tags18.zip / WILDFILE.DOC < prev    next >
Text File  |  1992-01-06  |  15KB  |  387 lines

  1.  
  2.  
  3.                        WildFile for MS-DOS systems
  4.  
  5.                  A *IX SH style file globber written in C
  6.                    V1.20 Dedicated to the Public Domain
  7.  
  8.                                January 07, 1992
  9.                                  J. Kercheval
  10.                          [72450,3702] -- johnk@wrq.com
  11.  
  12.  
  13.  
  14. 01-07-92
  15.  
  16. This is V1.20 of Wildfile.
  17.  
  18. Thanks to F. C. Smith for a bug fix when expanding paths of the form
  19. c:* rather than the fully qualified c:\*.  This version also utilizes
  20. the generic match code from MATCH V1.20 with appropriate ifdef's for
  21. use with the MSDOS path follow character.
  22.  
  23.                                 jbk
  24.  
  25.  
  26. 05-13-91
  27.  
  28. This is V1.14 of Wildfile.
  29.  
  30. Thanks to David Kirschbaum of Toad Hall for adding support for Turbo C
  31. V2.0.
  32.  
  33.                                 jbk
  34.  
  35.  
  36. 05-07-91
  37.  
  38. This is V1.13 of Wildfile, a *IX SH style file Globber.
  39.  
  40. The purpose of this code is to enable the programmer to allow *real*
  41. wildcard file specification.  The UNIX (*IX) SH style wildcard system
  42. has been around for decades and there is absolutely no good reason for
  43. it's lack of presence within MS/PC DOS and its associated tools.
  44.  
  45. I submit this without copyright and with the clear understanding that
  46. this code may be used by anyone, for any reason, with any modifications
  47. and without any guarantees, warrantee or statements of usability of any
  48. sort.
  49.  
  50.  
  51.                                 jbk
  52.  
  53.  
  54.  
  55. *IX SH style wildcard file globbing
  56. ===================================
  57.  
  58. The unix style of wildcard globbing (matching files to a wildcard
  59. specification) is quite a bit more flexible than the standard
  60. approach seen on the MS\PC DOS machines.  The full power of *IX SH
  61. style regular expressions are allowed to specify a file name.  For
  62. instance:
  63.     "*t*"           would match to the filenames test.doc, wet.goo,
  64.                     itsy.bib, foo.tic, etc.
  65.     "th?[a-eg]."    would match to any file without an extension,
  66.                     whose first two letters were "th", with any third
  67.                     letter and whose last letter was a,b,c,d,e or g.
  68.                     (ie. thug, thod, thud, etc.)
  69.     "*"             would match all filenames.
  70.  
  71. The regular expression syntax is described in detail in the source
  72. code and below.
  73.  
  74.  
  75. Implementation
  76. ==============
  77.  
  78. The implementation of the wildcard package is similar in type to the
  79. standard MS/PC DOS function calls for file searches.  There is a
  80. find_firstfile call which begins a search initially and a
  81. find_nextfile call which continues a previous search.  This approach
  82. will normally yield a very quick port from existing *standard*
  83. implementations of wildcard file searching.
  84.  
  85. The include file WILDFILE.H does a good job of describing the
  86. specifics required here.
  87.  
  88.  
  89. WD
  90. ==
  91.  
  92. WD is a very quick implementation of a directory lister to try to
  93. show the usage of the wildfile module as intended.  The program is a
  94. fully functional program complete with usage messages and command
  95. line argument parsing.
  96.  
  97.  
  98. Languages
  99. =========
  100.  
  101. WILDFILE (and its associated module MATCH) were developed and
  102. compiled using both MicroSoft C V6.00A and Borland C++.
  103.  
  104.  
  105.  
  106. ============================================================================
  107.  
  108. ============================================================================
  109.  
  110.  
  111.  
  112. MATCH120
  113.  
  114.  
  115.  
  116.  
  117.                     REGEX Globber (Wild Card Matching)
  118.  
  119.                A *IX SH style pattern matcher written in C
  120.                    V1.20 Dedicated to the Public Domain
  121.  
  122.                                January 07, 1992
  123.                                  J. Kercheval
  124.                          [72450,3702] -- johnk@wrq.com
  125.  
  126.  
  127.  
  128. 01-07-91
  129.  
  130. This is V1.2 of REGEX Globber.
  131.  
  132. To clarify code I have added defines for the standard characters used
  133. within a match pattern and have reformatted the source code.  There
  134. is an internal define to allow this code to be used in filename
  135. regular expression globbing for the MSDOS platform.  This consisted
  136. of disabling the use of the literal escape outside of a range so that
  137. path follows (ie '\') would be handled correctly.
  138.  
  139.                                 jbk
  140.  
  141. 03-12-91
  142.  
  143. This is V1.1 of REGEX Globber.
  144.  
  145.  
  146. 03-12-91
  147.  
  148. I have made a few changes to the match module which do several
  149. things.  The first change is an increase in bad pattern detection
  150. during a match.  It was possible, in some very unlikely cases, to
  151. cook up a pattern which should result in an early bad match but which
  152. would actually cause problems for the parser.  In particular, the
  153. subcase where the literal escape '\' within an open [..] construct at
  154. the end of a pattern would end up with incorrect results.  I
  155. proceeded to create some of these patterns, added them to my test
  156. battery and dove straight in.
  157.  
  158. In the interim I came across a posting to CompuServe (SMATCH by Stan
  159. Aderman) which attempted to create a completely non-recursive
  160. implementation of match (I am not sure this is possible without
  161. explicitly creating your own stack or it's equivalent, like a binary
  162. tree :-{ ).  While the code could not correctly handle multiple '*'
  163. characters in the pattern, there was a few interesting ideas in the
  164. posting.  On some occasions, running match over and over would be
  165. counter productive, especially and in particular when you have a bad
  166. pattern.  I have added a fast routine, is_valid_pattern(), to
  167. determine if the current pattern is well formed which should address
  168. this situation.
  169.  
  170. One other idea which I unceremoniously lifted from SMATCH was (in
  171. hindsight a pretty obvious feature) the return of a meaningful error
  172. code from both the pattern validity routine and from match() (which I
  173. renamed to matche()).
  174.  
  175. I also took some time to experiment with some ways to cut some time
  176. off the routine.  Since this is a SH pattern matcher whose intent is
  177. primarily for shell functions, the changes could not be algorithmic
  178. changes which relied on speedup over large input.  The differences in
  179. execution time were not very significant, but I did manage to gain
  180. approximately 5%-10% speedup when I removed the literal escape ('\')
  181. parsing and pattern error checking.  For those of you who want to use
  182. this for filename wildcard usage, I would recommend doing this since
  183. you should use is_valid_pattern and is_pattern before going out and
  184. finding filenames and the dos path delimiter defaults to the
  185. character used for the literal escape ('\') anyway (Note: I will be
  186. soon be releasing a *IX style file parser in the FINDFILE, FINDNEXT
  187. flavor soon to a Public Domain archive near you :-) ).
  188.  
  189. I also briefly toyed with adding a non-SH regex character '+' to this
  190. module but removed it again.  It was a performance hit of a few
  191. percent and would be mostly unused in any event.  For those
  192. interested in such a feature, the changes are truly minimal.  The
  193. required extra work is: 
  194.  
  195.    1) One case statement each in is_pattern() and is_valid_pattern() 
  196.    2) One case statement in matche()
  197.    3) One addition to a while conditional in matche_after_star()
  198.    4) One addition to an if conditional in matche_after_star()
  199.  
  200. Hint:  The case statements are all "case '+'" and the conditionals
  201.        have "|| *p == '+' " added to them.
  202.  
  203. I have also included a file (MATCH.DOC) which describes matches use and
  204. background as well as a little about regular expressions.
  205.  
  206.                                 jbk
  207.  
  208. 02-24-91
  209.  
  210. This is V1.01 of REGEX Globber.
  211.  
  212.  
  213. 02-22-91 Seattle, WA
  214.  
  215. Hmm. Choke. (Foot in mouth). After griping about buggy routines and
  216. literally seconds after posting this code the first time,  I received
  217. a wonderful new test evaluation tool which allows you to perform
  218. coverage analysis during testing.  Sure enough I found that about
  219. 25% of the paths in the program were never traversed in my current
  220. test battery.  After swallowing my (overly large) pride and coming
  221. up with a test battery which covered the entire path of the program
  222. I found a couple of minor logic bugs involving literal escapes (\)
  223. within other patterns (ie [..] and * sequences).  I have repackaged
  224. these routines and included also the makefile I use and the test
  225. battery I use to make things a bit easier.
  226.  
  227.                                 jbk
  228.  
  229. 02-20-91 Seattle, WA
  230.  
  231. Here is a *IX wildcard globber I butchered, hacked and cajoled together
  232. after seeing and hearing about and becoming disgusted with several similar
  233. routines which had one or more of the following attributes:  slow, buggy,
  234. required large levels of recursion on matches, required grotesque levels
  235. of recursion on failing matches using '*', full of caveats about usability
  236. or copyrights.
  237.  
  238. I submit this without copyright and with the clear understanding that
  239. this code may be used by anyone, for any reason, with any modifications
  240. and without any guarantees, warrantee or statements of usability of any
  241. sort.
  242.  
  243. Having gotten those cow chips out of the way, these routines are fairly
  244. well tested and reasonably fast.  I have made an effort to fail on all
  245. bad patterns and to quickly determine failing '*' patterns.  This parser
  246. will also do quite a bit of the '*' matching via quick linear loops versus
  247. the standard blind recursive descent.
  248.  
  249. This parser has been submitted to profilers at various stages of development
  250. and has come through quite well.  If the last millisecond is important to
  251. you then some time can be shaved by using stack allocated variables in
  252. place of many of the pointer follows (which may be done fairly often) found
  253. in regex_match and regex_match_after_star (ie *p, *t).
  254.  
  255. No attempt is made to provide general [pat,pat] comparisons.  The specific
  256. subcases supplied by these routines is [pat,text] which is sufficient
  257. for the large majority of cases (should you care).
  258.  
  259. Since regex_match may return one of three different values depending upon
  260. the pattern and text I have made a simple shell for convenience (match()).
  261. Also included is an is_pattern routine to quickly check a potential pattern
  262. for regex special characters.  I even placed this all in a header file for
  263. you lazy folks!
  264.  
  265. Having said all that, here is my own reinvention of the wheel.  Please
  266. enjoy it's use and I hope it is of some help to those with need ....
  267.  
  268.  
  269.                                 jbk
  270.  
  271.  
  272.  
  273.  
  274. *IX SH style Regular Expressions
  275. ================================
  276.  
  277. The *IX command SH is a working shell similar in feel to the MSDOS
  278. shell COMMAND.COM.  In point of fact much of what we see in our
  279. familiar DOS PROMPT was gleaned from the early UNIX shells available
  280. for many of machines the people involved in the computing arena had
  281. at the time of the development of DOS and it's much maligned
  282. precursor CP/M (although the UNIX shells were and are much more
  283. flexible and powerful then those on the current flock of micro
  284. machines).  The designers of DOS and CP/M did some fairly strange
  285. things with their command processor and OS.  One of those things was
  286. to only selectively adopt the regular expressions allowed within the
  287. *IX shells.  Only '?' and '*' were allowed in filenames and even with
  288. these the '*' was allowed only at the end of a pattern and in fact
  289. when used to specify the filename the '*' did not apply to extension.
  290. This gave rise to the all too common expression "*.*".
  291.  
  292. REGEX Globber is a SH pattern matcher.  This allows such
  293. specifications as *75.zip or * (equivalent to *.* in DOS lingo).
  294. Expressions such as [a-e]*t would fit the name "apple.crt" or
  295. "catspaw.bat" or "elegant".  This allows considerably wider
  296. flexibility in file specification, general parsing or any other
  297. circumstance in which this type of pattern matching is wanted.
  298.  
  299. A match would mean that the entire string TEXT is used up in matching
  300. the PATTERN and conversely the matched TEXT uses up the entire
  301. PATTERN.
  302.  
  303. In the specified pattern string:
  304.      `*' matches any sequence of characters (zero or more)
  305.      `?' matches any character
  306.      `\' suppresses syntactic significance of a special character
  307.      [SET] matches any character in the specified set,
  308.      [!SET] or [^SET] matches any character not in the specified set.
  309.  
  310. A set is composed of characters or ranges; a range looks like
  311. 'character hyphen character' (as in 0-9 or A-Z).  [0-9a-zA-Z_] is the
  312. minimal set of characters allowed in the [..] pattern construct.
  313. Other characters are allowed (ie. 8 bit characters) if your system
  314. will support them (it almost certainly will).
  315.  
  316. To suppress the special syntactic significance of any of `[]*?!^-\',
  317. and match the character exactly, precede it with a `\'.
  318.  
  319. To view several examples of good and bad patterns and text see the
  320. output of MATCHTST.BAT
  321.  
  322.  
  323.  
  324. MATCH() and MATCHE()
  325. ====================
  326.  
  327. The match module as written has two parsing routines, one is matche()
  328. and the other is match().  Since match() is a call to matche() which
  329. simply has its output mapped to a BOOLEAN value (ie TRUE if pattern
  330. matches or FALSE otherwise), I will concentrate my explanations here
  331. on matche().
  332.  
  333. The purpose of matche() is to match a pattern against a string of
  334. text (usually a file name or specification).  The match routine has
  335. extensive pattern validity checking built into it as part of the
  336. parser and allows for a robust pattern match.
  337.  
  338. The parser gives an error code on return of type int.  The error code
  339. will be one of the the following defined values (defined in match.h):
  340.  
  341.     MATCH_PATTERN  - bad pattern or misformed pattern
  342.     MATCH_LITERAL  - match failed on character match (standard
  343.                      character)
  344.     MATCH_RANGE    - match failure on character range ([..] construct)
  345.     MATCH_ABORT    - premature end of text string (pattern longer
  346.                      than text string)
  347.     MATCH_END      - premature end of pattern string (text longer
  348.                      than pattern called for)
  349.     MATCH_VALID    - valid match using pattern
  350.  
  351. The functions are declared as follows:
  352.  
  353.     BOOLEAN match (char *pattern, char *text);
  354.  
  355.     int     matche(register char *pattern, register char *text);
  356.  
  357.  
  358.  
  359. IS_VALID_PATTERN() and IS_PATTERN()
  360. ===================================
  361.  
  362. There are two routines for determining properties of a pattern
  363. string.  The first, is_pattern(), is designed simply to determine if
  364. some character exists within the text which is consistent with a SH
  365. regular expression (this function returns TRUE if so and FALSE if
  366. not).  The second, is_valid_pattern() is designed to check the
  367. validity of a given pattern string (TRUE return if valid, FALSE if
  368. not).  By 'validity', I mean well formed or syntactically correct.
  369.  
  370. In addition, is_valid_pattern() has as one of it's parameters a
  371. return code for determining the type of error found in the pattern if
  372. one exists.  The error codes are as follows and defined in match.h:
  373.  
  374.     PATTERN_VALID - pattern is well formed
  375.     PATTERN_ESC   - pattern has invalid literal escape ('\' at end of
  376.                     pattern)
  377.     PATTERN_RANGE - [..] construct has a no end range in a '-' pair
  378.                     (ie [a-])
  379.     PATTERN_CLOSE - [..] construct has no end bracket (ie [abc-g )
  380.     PATTERN_EMPTY - [..] construct is empty (ie [])
  381.  
  382. The functions are declared as follows:
  383.  
  384.     BOOLEAN is_valid_pattern (char *pattern, int *error_type);
  385.  
  386.     BOOLEAN is_pattern (char *pattern);
  387.